﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WeMakeSP.Platform.SharePoint.MVP;
using WeMakeSP.WebComponents.RSSAdvancedReaderWebPart.Exceptions;

namespace WeMakeSP.WebComponents.RSSAdvancedReaderWebPart
{
    /// <summary>
    /// Represens the RSS advanced reader presenter.
    /// </summary>
    public class RSSAdvancedReaderPresenter : PresenterBase, IRSSAdvancedReaderPresenter
    {
        #region Fields

        /// <summary>
        /// The RSS advanced reader model.
        /// </summary>
        private IRSSAdvancedReaderModel model;

        /// <summary>
        /// The RSS advanced reader view.
        /// </summary>
        private IRSSAdvancedReaderView view;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="RSSAdvancedReaderPresenter"/> class.
        /// </summary>
        /// <param name="view">The RSS advanced reader view.</param>
        /// <param name="model">The RSS advanced reader model.</param>
        public RSSAdvancedReaderPresenter(IRSSAdvancedReaderView view, IRSSAdvancedReaderModel model) :
            base(view)
        {
            // Guard.

            if (view == null)
            {
                throw new ArgumentNullException("view");
            }

            if (model == null)
            {
                throw new ArgumentNullException("model");
            }

            // Set the view.

            this.view = view;

            // Set the model.

            this.model = model;

            // Register this instance to events.

            this.RegisterPresenterToEvents();
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the current feed.
        /// </summary>
        /// <value>The current feed.</value>
        public RSSAdvancedReaderFeedConfiguration CurrentFeed
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the current item.
        /// </summary>
        /// <value>The current item.</value>
        public RSSAdvancedReaderFeedItemConfiguration CurrentItem
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the status.
        /// </summary>
        /// <value>The status.</value>
        public RSSAdvancedReaderStatus Status
        {
            get;
            set;
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Handles the presentation model exception.
        /// </summary>
        /// <param name="ex">The exception.</param>
        /// <returns>Indicates if the exception was handled.</returns>
        protected override bool HandlePresentationModelException(Exception ex)
        {
            return base.HandlePresentationModelException(ex);
        }

        /// <summary>
        /// Loads the data.
        /// </summary>
        private void LoadData()
        {
            RSSAdvancedReaderFeedConfigurationCollection feedConfigurations;
            RSSAdvancedReaderFeedCollection feeds;

            switch (this.Status)
            {
                case RSSAdvancedReaderStatus.FirstLoad:

                    feedConfigurations =
                        RSSAdvancedReaderConfigurationLoader.Load(this.view);

                    feeds =
                        this.model.GetFeeds(feedConfigurations);

                    this.view.DataSource = feeds;

                    break;
                case RSSAdvancedReaderStatus.FeedRefresh:

                    feedConfigurations =
                       RSSAdvancedReaderConfigurationLoader.Load(this.view);

                    // Load only the current feed.

                    foreach (RSSAdvancedReaderFeedConfiguration feedConfiguration in feedConfigurations)
                    {
                        feedConfiguration.Load = true;

                        if (feedConfiguration.Link.Equals(this.CurrentFeed.Link) == true)
                        {                          
                            // Set the current item limit.

                            feedConfiguration.Limit = this.CurrentFeed.Limit;
                        }
                    }

                    feeds =
                        this.model.GetFeeds(feedConfigurations);

                    this.view.DataSource = feeds;

                    break;
                case RSSAdvancedReaderStatus.FeedShowAll:

                    feedConfigurations =
                       RSSAdvancedReaderConfigurationLoader.Load(this.view);

                    foreach (RSSAdvancedReaderFeedConfiguration feedConfiguration in feedConfigurations)
                    {
                        feedConfiguration.Load = true;

                        if (feedConfiguration.Link.Equals(this.CurrentFeed.Link) == true)
                        {
                            // Set no limit to the feed.

                            feedConfiguration.Limit = 0;
                        }
                    }

                    feeds =
                        this.model.GetFeeds(feedConfigurations);

                    this.view.DataSource = feeds;

                    break;
                case RSSAdvancedReaderStatus.FeedItemShowBody:

                    feedConfigurations =
                      RSSAdvancedReaderConfigurationLoader.Load(this.view);

                    // Load only the current feed.

                    foreach (RSSAdvancedReaderFeedConfiguration feedConfiguration in feedConfigurations)
                    {
                        feedConfiguration.Load = true;

                        if (feedConfiguration.Link.Equals(this.CurrentFeed.Link) == true)                        
                        {    
                            feedConfiguration.Limit = this.CurrentFeed.Limit;
                        }
                    }

                    feeds =
                        this.model.GetFeeds(feedConfigurations);

                    // Get the feed.

                    RSSAdvancedReaderFeed feed =
                        feeds.Where(filter => filter.Link == this.CurrentFeed.Link).FirstOrDefault();

                    // Get the item.

                    RSSAdvancedReaderFeedItem feedItem =
                        feed.Items.Where(filter => filter.Link == this.CurrentItem.Link).FirstOrDefault();

                    // Set the item view to expanded.

                    feedItem.View = RSSAdvancedReaderItemView.Expanded;

                    this.view.DataSource = feeds;

                    break;
                default:
                    throw new NotImplementedException("RSSAdvancedReaderStatus");
            }
        }

        /// <summary>
        /// Registers the presenter to events.
        /// </summary>
        private void RegisterPresenterToEvents()
        {
            this.view.PreRender += new EventHandler(this.ViewPreRenderEventHandler);
            this.view.Load += new EventHandler(this.ViewLoadEventHandler);
            this.view.FeedRefreshing += new FeedRefresh(this.ViewFeedRefreshingEventHandler);
            this.view.FeedShowingAll += new FeedRefresh(this.ViewFeedShowingAllEventHandler);
            this.view.FeedItemBodyDisplaying += new FeedItemRefresh(this.ViewFeedItemBodyDisplayingEventHandler);
        }

        /// <summary>
        /// Sets the view status.
        /// </summary>
        private void SetViewStatus()
        {
            // No configured feeds.

            if (this.view.Feeds == string.Empty)
            {
                throw new EmptyFeedConfigurationException();
            }
        }

        /// <summary>
        /// Views the feed item body displaying event handler.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="WeMakeSP.WebComponents.RSSAdvancedReaderWebPart.FeedItemRefreshEventArgs"/> instance containing the event data.</param>
        private void ViewFeedItemBodyDisplayingEventHandler(object sender, FeedItemRefreshEventArgs e)
        {
            this.Status = RSSAdvancedReaderStatus.FeedItemShowBody;

            this.CurrentFeed =
                new RSSAdvancedReaderFeedConfiguration()
                {
                    Link = e.FeedUrl
                };

            this.CurrentItem =
                new RSSAdvancedReaderFeedItemConfiguration()
                {
                    Link = e.FeedItem
                };
        }

        /// <summary>
        /// Views the feed refreshing event handler.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="WeMakeSP.WebComponents.RSSAdvancedReaderWebPart.FeedRefreshEventArgs"/> instance containing the event data.</param>
        private void ViewFeedRefreshingEventHandler(object sender, FeedRefreshEventArgs e)
        {
            this.Status = RSSAdvancedReaderStatus.FeedRefresh;

            this.CurrentFeed =
                new RSSAdvancedReaderFeedConfiguration()
                {
                    Link = e.FeedUrl,
                    Limit = e.ItemCount
                };
        }

        /// <summary>
        /// Views the feed showing all event handler.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="WeMakeSP.WebComponents.RSSAdvancedReaderWebPart.FeedRefreshEventArgs"/> instance containing the event data.</param>
        private void ViewFeedShowingAllEventHandler(object sender, FeedRefreshEventArgs e)
        {
            this.Status = RSSAdvancedReaderStatus.FeedShowAll;

            this.CurrentFeed =
                new RSSAdvancedReaderFeedConfiguration()
                {
                    Link = e.FeedUrl
                };
        }

        /// <summary>
        /// Views the load event handler.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void ViewLoadEventHandler(object sender, EventArgs e)
        {
        }

        /// <summary>
        /// Views the pre render event handler.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void ViewPreRenderEventHandler(object sender, EventArgs e)
        {
            try
            {
                // Load the data.

                this.LoadData();

                // Set the view status.

                this.SetViewStatus();

                // Data bind the view.

                this.view.DataBind();
            }
            catch (Exception ex)
            {
                if (this.HandlePresentationModelException(ex) == false)
                {
                    throw;
                }
            }
        }

        #endregion
    }
}
